package com.chen.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chen.blog.common.api.CommonResult;
import com.chen.blog.common.constant.MessageConstant;
import com.chen.blog.mapper.*;
import com.chen.blog.model.*;
import com.chen.blog.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chen.blog.vo.PwdVo;
import com.chen.blog.vo.ResetPwdVo;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author chen
 * @since 2022-01-24
 */
@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private BlogMapper blogMapper;

    @Autowired
    private BlogTagMapper blogTagMapper;

    @Autowired
    private ScoreMapper scoreMapper;

    @Autowired
    private CommentMapper commentMapper;

    @Autowired
    private CollectMapper collectMapper;

    @Autowired
    private FollowMapper followMapper;

    @Autowired
    @Lazy
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JavaMailSender javaMailSender;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private DefaultKaptcha defaultKaptcha;

    /**
     * 用户注册功能实现
     *
     * @param user
     * @return
     */
    @Override
    public CommonResult add(User user) {
        User realUser = userMapper.selectOne(new QueryWrapper<User>().eq("username", user.getUsername()));
        if (realUser != null) {
            return CommonResult.error(MessageConstant.USER_NAME_FAIL);
        }
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        if (userMapper.insert(user) > 0) {
            return CommonResult.success(MessageConstant.ADD_USER_SUCCESS);
        }
        return CommonResult.error(MessageConstant.ADD_USER_FAIL);
    }

    /**
     * 批量删除用户功能实现
     *
     * @param ids
     * @return
     */
    @Override
    public CommonResult deleteByIds(Integer[] ids) {
        for (Integer id : ids) {
            User user = userMapper.selectById(id);
            if (user != null) {
                List<Blog> blogList = blogMapper.selectList(new QueryWrapper<Blog>().eq("user_id", user.getId()));
                if (blogList != null && blogList.size() > 0) {
                    for (Blog blog : blogList) {
                        blogTagMapper.delete(new QueryWrapper<BlogTag>().eq("blog_id", blog.getId()));
                        blogMapper.delete(new QueryWrapper<Blog>().eq("user_id", blog.getUserId()));
                    }
                }
                scoreMapper.delete(new QueryWrapper<Score>().eq("user_id", user.getId()));
                commentMapper.delete(new QueryWrapper<Comment>().eq("user_id", user.getId()));
                collectMapper.delete(new QueryWrapper<Collect>().eq("user_id", user.getId()));
                followMapper.delete(new QueryWrapper<Follow>().eq("user_id", user.getId()));
            }
        }
        if (userMapper.deleteBatchIds(Arrays.asList(ids)) > 0) {
            return CommonResult.success(MessageConstant.DELETE_POSITION_SUCCESS);
        }
        return CommonResult.error(MessageConstant.DELETE_POSITION_FAIL);
    }

    /**
     * 更新用户功能实现
     *
     * @param user
     * @return
     */
    @Override
    public CommonResult updateByParam(User user) {
        User realUser = userMapper.selectOne(new QueryWrapper<User>().eq("username", user.getUsername()));
        if (realUser != null) {
            return CommonResult.error(MessageConstant.USER_NAME_FAIL);
        }
        user.setUpdateTime(LocalDateTime.now());
        if (userMapper.updateById(user) == 1) {
            SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(user, null, null));
            return CommonResult.success(MessageConstant.UPDATE_POSITION_SUCCESS);
        }
        return CommonResult.error(MessageConstant.UPDATE_POSITION_FAIL);
    }

    /**
     * 分页复合查询用户功能实现
     *
     * @param currentPage
     * @param pageSize
     * @param user
     * @return
     */
    @Override
    public CommonResult getByParamAndPage(Integer currentPage, Integer pageSize, User user) {
        Page<User> page = userMapper.selectPage(new Page<>(currentPage, pageSize), getWrapper(user));
        if (currentPage > page.getPages()) {
            return CommonResult.success(null, userMapper.selectPage(new Page<>(page.getPages(), pageSize), getWrapper(user)));
        }
        return CommonResult.success(null, page);
    }

    /**
     * 更新用户密码功能实现
     *
     * @param pwdVo
     * @return
     */
    @Override
    public CommonResult updatePwd(PwdVo pwdVo) {
        User user = userMapper.selectById(pwdVo.getId());
        if (passwordEncoder.matches(pwdVo.getOldPwd(), user.getPassword())) {
            user.setPassword(passwordEncoder.encode(pwdVo.getNewPwd()));
            if (userMapper.updateById(user) == 1) {
                return CommonResult.success(MessageConstant.UPDATE_POSITION_SUCCESS);
            }
            return CommonResult.error(MessageConstant.UPDATE_POSITION_FAIL);
        }
        return CommonResult.error(MessageConstant.PWD_FAIL);
    }

    /**
     * 重置密码功能实现
     *
     * @param resetPwdVo
     * @return
     */
    @Override
    public CommonResult resetPwd(ResetPwdVo resetPwdVo) {
        String captcha = (String) redisTemplate.opsForValue().get("emailCode");
        if (StringUtils.isEmpty(resetPwdVo.getCode()) || !captcha.equalsIgnoreCase(resetPwdVo.getCode())) {
            return CommonResult.error(MessageConstant.CODE_FAIL);
        }
        if (userMapper.update(null, new UpdateWrapper<User>().eq("username", resetPwdVo.getUsername())
                .eq("email", resetPwdVo.getEmail()).set("password", passwordEncoder.encode(resetPwdVo.getNewPwd()))) == 1) {
            return CommonResult.success(MessageConstant.RESET_PWD_SUCCESS);
        }
        return CommonResult.error(MessageConstant.RESET_PWD_FAIL);
    }

    /**
     * 发送邮箱验证码功能实现
     *
     * @param email
     * @return
     */
    @Override
    public CommonResult sendCode(String email) {
        // 构建一个邮件对象
        SimpleMailMessage message = new SimpleMailMessage();
        // 设置邮件主题
        message.setSubject("重置密码");
        // 设置邮件发送者，这个跟application.yml中设置的要一致
        message.setFrom("cgy20021206@126.com");
        // 设置邮件接收者，可以有多个接收者，中间用逗号隔开，以下类似
        // message.setTo("10*****16@qq.com","12****32*qq.com");
        message.setTo(email);
        // 设置邮件发送日期
        message.setSentDate(new Date());
        String text = defaultKaptcha.createText();
        // 设置邮件的正文
        message.setText("验证码：" + text);
        redisTemplate.opsForValue().set("emailCode", text, 2, TimeUnit.MINUTES);
        // 发送邮件
        javaMailSender.send(message);
        return CommonResult.success(MessageConstant.EMAIL_CODE_SUCCESS);
    }

    /**
     * 获取指定用户信息功能实现
     *
     * @param username
     * @return
     */
    @Override
    public User getUserByUserName(String username) {
        return userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
    }

    //封装查询条件
    private QueryWrapper<User> getWrapper(User user) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.like(!StringUtils.isEmpty(user.getUsername()), "username", user.getUsername())
                .like(!StringUtils.isEmpty(user.getNickname()), "nickname", user.getNickname())
                .like(!StringUtils.isEmpty(user.getEmail()), "email", user.getEmail())
                .like(!StringUtils.isEmpty(user.getType()), "type", user.getType());
        return wrapper;
    }

}
